package com.OutterSpace;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.primitive.Rectangle;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.scene.Scene.IOnSceneTouchListener;
import org.anddev.andengine.entity.scene.background.ParallaxBackground.ParallaxEntity;
import org.anddev.andengine.entity.shape.Shape;
import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.entity.util.FPSLogger;
import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;
import org.anddev.andengine.extension.physics.box2d.util.Vector2Pool;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.util.modifier.ease.EaseBackIn;
import org.anddev.andengine.util.modifier.ease.EaseBackInOut;
import org.anddev.andengine.util.modifier.ease.EaseBackOut;
import org.anddev.andengine.util.modifier.ease.EaseBounceIn;
import org.anddev.andengine.util.modifier.ease.EaseBounceInOut;
import org.anddev.andengine.util.modifier.ease.EaseBounceOut;
import org.anddev.andengine.util.modifier.ease.EaseCircularIn;
import org.anddev.andengine.util.modifier.ease.EaseCircularInOut;
import org.anddev.andengine.util.modifier.ease.EaseCircularOut;
import org.anddev.andengine.util.modifier.ease.EaseCubicIn;
import org.anddev.andengine.util.modifier.ease.EaseCubicInOut;
import org.anddev.andengine.util.modifier.ease.EaseCubicOut;
import org.anddev.andengine.util.modifier.ease.EaseElasticIn;
import org.anddev.andengine.util.modifier.ease.EaseElasticInOut;
import org.anddev.andengine.util.modifier.ease.EaseElasticOut;
import org.anddev.andengine.util.modifier.ease.EaseExponentialIn;
import org.anddev.andengine.util.modifier.ease.EaseExponentialInOut;
import org.anddev.andengine.util.modifier.ease.EaseExponentialOut;
import org.anddev.andengine.util.modifier.ease.EaseLinear;
import org.anddev.andengine.util.modifier.ease.EaseQuadIn;
import org.anddev.andengine.util.modifier.ease.EaseQuadInOut;
import org.anddev.andengine.util.modifier.ease.EaseQuadOut;
import org.anddev.andengine.util.modifier.ease.EaseQuartIn;
import org.anddev.andengine.util.modifier.ease.EaseQuartInOut;
import org.anddev.andengine.util.modifier.ease.EaseQuartOut;
import org.anddev.andengine.util.modifier.ease.EaseQuintIn;
import org.anddev.andengine.util.modifier.ease.EaseQuintInOut;
import org.anddev.andengine.util.modifier.ease.EaseQuintOut;
import org.anddev.andengine.util.modifier.ease.EaseSineIn;
import org.anddev.andengine.util.modifier.ease.EaseSineInOut;
import org.anddev.andengine.util.modifier.ease.EaseSineOut;
import org.anddev.andengine.util.modifier.ease.EaseStrongIn;
import org.anddev.andengine.util.modifier.ease.EaseStrongInOut;
import org.anddev.andengine.util.modifier.ease.EaseStrongOut;
import org.anddev.andengine.util.modifier.ease.IEaseFunction;

import android.hardware.SensorManager;
import android.util.DisplayMetrics;
import android.view.MotionEvent;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;

public class OutterSpaceActivity extends BaseGameActivity implements IOnSceneTouchListener {
	// ===========================================================
	// Constants
	// ===========================================================

	private static final int CAMERA_WIDTH = 480;
	private static final int CAMERA_HEIGHT = 320;

	// ===========================================================
	// Fields
	// ===========================================================

	private Camera mCamera;

	private BitmapTextureAtlas mBitmapTextureAtlas;
	private TiledTextureRegion mPlayerTextureRegion;
	private TiledTextureRegion mBox;
	private TiledTextureRegion mEnemyTextureRegion;

	private BitmapTextureAtlas mAutoParallaxBackgroundTexture;

	private TextureRegion mParallaxLayerBack;
	private TextureRegion mParallaxLayerMid;
	private TextureRegion mParallaxLayerFront;
	
	private Body body;
	private Body body1;
	
	private GameControll mGameControll;
	private PhysicsWorld mPhysicsWorld;
	float momentTime;
	
	private static final IEaseFunction[][] EASEFUNCTIONS = new IEaseFunction[][]{
		new IEaseFunction[] {
				EaseLinear.getInstance(),
				EaseLinear.getInstance(),
				EaseLinear.getInstance()
		},
		new IEaseFunction[] {
				EaseBackIn.getInstance(),
				EaseBackOut.getInstance(),
				EaseBackInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseBounceIn.getInstance(),
				EaseBounceOut.getInstance(),
				EaseBounceInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseCircularIn.getInstance(),
				EaseCircularOut.getInstance(),
				EaseCircularInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseCubicIn.getInstance(),
				EaseCubicOut.getInstance(),
				EaseCubicInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseElasticIn.getInstance(),
				EaseElasticOut.getInstance(),
				EaseElasticInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseExponentialIn.getInstance(),
				EaseExponentialOut.getInstance(),
				EaseExponentialInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseQuadIn.getInstance(),
				EaseQuadOut.getInstance(),
				EaseQuadInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseQuartIn.getInstance(),
				EaseQuartOut.getInstance(),
				EaseQuartInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseQuintIn.getInstance(),
				EaseQuintOut.getInstance(),
				EaseQuintInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseSineIn.getInstance(),
				EaseSineOut.getInstance(),
				EaseSineInOut.getInstance()
		},
		new IEaseFunction[] {
				EaseStrongIn.getInstance(),
				EaseStrongOut.getInstance(),
				EaseStrongInOut.getInstance()
		}
	};
	
	ScrollableParallaxBackground background;
	AnimatedSprite player;
	AnimatedSprite box1;

	// ===========================================================
	// Constructors
	// ===========================================================

	// ===========================================================
	// Getter & Setter
	// ===========================================================

	// ===========================================================
	// Methods for/from SuperClass/Interfaces
	// ===========================================================

	public Engine onLoadEngine() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
		this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
		return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(getScreenResolutionRatio()), this.mCamera));
	}

	private float getScreenResolutionRatio() {
		DisplayMetrics dm = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		return ((float) dm.widthPixels) / ((float) dm.heightPixels);
	}
	
	public void onLoadResources() {
		BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
		
		this.mBitmapTextureAtlas = new BitmapTextureAtlas(512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		this.mPlayerTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "baby.png", 0, 0, 4, 1);
		this.mBox = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "face_box_tiled.png", 0, 115, 2, 1);

		this.mAutoParallaxBackgroundTexture = new BitmapTextureAtlas(1024, 1024, TextureOptions.DEFAULT);
		this.mParallaxLayerFront = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mAutoParallaxBackgroundTexture, this, "front.png", 0, 0);
		this.mParallaxLayerBack = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mAutoParallaxBackgroundTexture, this, "back.png", 0, 320);
		this.mParallaxLayerMid = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mAutoParallaxBackgroundTexture, this, "mid.png", 0, 640);

		this.mEngine.getTextureManager().loadTextures(this.mBitmapTextureAtlas, this.mAutoParallaxBackgroundTexture);
	}
	
	@Override
	public Scene onLoadScene() {
		
		this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, SensorManager.GRAVITY_EARTH), false);
		
		final Scene scene = new Scene();
		
		
//		ParallaxEntity parallaxFront = new ParallaxEntity(-10.0f, new Sprite(0, 0, this.mParallaxLayerFront));
//		final AutoParallaxBackground autoParallaxBackground = new AutoParallaxBackground(0, 0, 0, 5);
//		autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, 0, this.mParallaxLayerBack)));
//		autoParallaxBackground.attachParallaxEntity(new ParallaxEntity(-2.0f, new Sprite(0, 0, this.mParallaxLayerMid)));
//		autoParallaxBackground.attachParallaxEntity(parallaxFront);
//		scene.setBackground(autoParallaxBackground);
		
/*		final ParallaxBackground parallaxBack = new ParallaxBackground(0,0,0);
		parallaxBack.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, 0, this.mParallaxLayerBack)));
		parallaxBack.attachParallaxEntity(new ParallaxEntity(-2.0f, new Sprite(0, 0, this.mParallaxLayerMid)));
		parallaxBack.attachParallaxEntity(new ParallaxEntity(-10.0f, new Sprite(0, 0, this.mParallaxLayerFront)));
		scene.setBackground(parallaxBack);
*/		
		/* Calculate the coordinates for the face, so its centered on the camera. */
		final int playerX = (CAMERA_WIDTH) / 2;
		final int playerY = CAMERA_HEIGHT - this.mPlayerTextureRegion.getTileHeight() - 50;
		
		final int BoxX = (CAMERA_WIDTH)-50;
		final int BoxY = CAMERA_HEIGHT - this.mPlayerTextureRegion.getTileHeight() - 50;
		  
		final Shape ground = new Rectangle(0, CAMERA_HEIGHT-50, CAMERA_WIDTH, CAMERA_HEIGHT-50);
		final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.5f, 0.5f);
		PhysicsFactory.createBoxBody(mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef);
//		scene.attachChild(ground);
		
		/* Create two sprits and add it to the scene. */
		player = new AnimatedSprite(playerX, playerY, this.mPlayerTextureRegion){                       
				@Override
                public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                // TODO Auto-generated method stub
                final Vector2 velocity = Vector2Pool.obtain(mPhysicsWorld.getGravity().x * -0.5f,mPhysicsWorld.getGravity().y * -0.5f);
                body.setLinearVelocity(velocity);
                Vector2Pool.recycle(velocity);
               
                return true;
				}
		};
		box1 = new AnimatedSprite(BoxX, BoxY, this.mBox);                       
		FixtureDef faceBodyFixtureDef = PhysicsFactory.createFixtureDef(1000, -10000.0f, 0.0f);
		body = PhysicsFactory.createCircleBody(this.mPhysicsWorld, player, BodyType.DynamicBody, faceBodyFixtureDef);
		body1 = PhysicsFactory.createBoxBody(this.mPhysicsWorld, box1, BodyType.DynamicBody, faceBodyFixtureDef);
		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(player, body));
		mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(box1, body1));
		
//		player.setScaleCenterY(this.mPlayerTextureRegion.getTileHeight());
//		player.setScale(1);
		//player.animate(100);
		
		
		background = new ScrollableParallaxBackground(0, 0, 0, this.player,this.mCamera);
		background.attachParallaxEntity(new ParallaxEntity(0.0f, new Sprite(0, 0, this.mParallaxLayerBack)));
		background.attachParallaxEntity(new ParallaxEntity(-.1f, new Sprite(0, 0, this.mParallaxLayerMid)));
		background.attachParallaxEntity(new ParallaxEntity(-1.0f, new Sprite(0, 0, this.mParallaxLayerFront)));
		scene.setBackground(background);
		
		scene.attachChild(player);
		scene.attachChild(box1);
		
		
 
		
//		mGameControll = new GameControll(this.mCamera);
		scene.setOnSceneTouchListener(this);
		
		this.mEngine.registerUpdateHandler(new FPSLogger(){
		    @Override
		    public void onUpdate(float pSecondsElapsed) {
		    //	momentTime-=pSecondsElapsed*10;
		   // 	mCamera.setCenter(player.getX()+50, mCamera.getCenterY());
		    	player.setPosition(mCamera.getCenterX(), CAMERA_HEIGHT  -100);
		    //	scene.convertLocalToSceneCoordinates(pCoordinates)
		    }

		});
		
		scene.registerUpdateHandler(mPhysicsWorld);
		return scene;
	}
    

	public void onLoadComplete() {

	}
	
	private float mTouchX = 0, mTouchOffsetX = 0, mTouchY=0, mMoveX=0, mLastElapsedTime=0, mParallaxSpeed;
	
	@Override
	public boolean onSceneTouchEvent(Scene pScene, TouchEvent pTouchEvent) {
	
		if (pTouchEvent.getAction() == MotionEvent.ACTION_DOWN) {
			 mTouchX = pTouchEvent.getMotionEvent().getX();
			 mTouchY = pTouchEvent.getMotionEvent().getY();
			 player.setPosition(player.getX(), 50);
             final Vector2 velocity = Vector2Pool.obtain(mPhysicsWorld.getGravity().x * -0.5f,mPhysicsWorld.getGravity().y * -0.5f);
             body.setLinearVelocity(velocity);
  //           Vector2Pool.recycle(velocity);
        } else if (pTouchEvent.getAction() == MotionEvent.ACTION_MOVE) {
			 mMoveX = pTouchEvent.getMotionEvent().getX();

			mTouchOffsetX = (mMoveX - mTouchX);
			if(mTouchX>CAMERA_WIDTH/2 && mMoveX<mTouchX) mParallaxSpeed = 50; 
			if(mTouchX>CAMERA_WIDTH/2 && mMoveX>mTouchX) mParallaxSpeed = 500;
			if(mTouchX<CAMERA_WIDTH/2 && mMoveX>mTouchX) mParallaxSpeed = -50; 
			if(mTouchX<CAMERA_WIDTH/2 && mMoveX<mTouchX) mParallaxSpeed = -500; 
		//	float newScrollX = player.getX() - mTouchOffsetX;
			
			momentTime = pScene.getSecondsElapsedTotal() - mLastElapsedTime;
			background.cameraOffsetX = mParallaxSpeed; 
			box1.setPosition(box1.getX()-momentTime, box1.getY());
			final IEaseFunction[] currentEaseFunctionsSet = EASEFUNCTIONS[10];
		//	player.registerEntityModifier(  new MoveModifier(1, player.getX(), player.getX()+mTouchX, player.getY(), player.getY(), currentEaseFunctionsSet[1]));
			mLastElapsedTime = pScene.getSecondsElapsedTotal();
			
			//background.updateScrollEvents();
			
			
			//mTouchX = newX;
		}
		return true;

	}

	
}